package com.neusoft.neuiotms.dcam.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.neusoft.neuiotms.dcam.config.QRCodeConfig;

@Component
public class QRCodeMaker {

    @Autowired
    private QRCodeConfig qrCodeConfig;

    @Value("${dcam.qrcode.size:300}")
    private int PIC_WIDTH;

    @Value("${dcam.qrcode.size:300}")
    private int PIC_HEIGHT;

    @Value("${dcam.qrcode.size:300}")
    private int QR_SIZE;

    private static final int BLUE = 0xFF3ED547;
    private static final int WHITE = 0xFFFFFFFF;
    private static final int BLACK = 0xFF000000;
    //    private static final int RED = 0xFFFF0000;

    private static final String IMG_FORMATE = "jpg";

    private static final int LOGO_BORDER_WIDTH = 2;//LOGO边框宽度
    private static final Color LOGO_BORDER_COLOR = Color.WHITE;//LOGO边框颜色

    // TODO:logo file path

    /**
     * 生成二维码图片
     *
     * @param info 二维码信息
     * @param out 目的图片地址
     */
    public void MakeQRCode(final String info,final String title, final String out) throws WriterException, IOException {
        final File outFile = new File(out);

        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }

        final BufferedImage image = this.toTopAndButtonImg(this.getBitMatrix(info), true, title, title);

        ImageIO.write(image, QRCodeMaker.IMG_FORMATE, outFile);

    }

    /**
     * 生成带logo的二维码图片
     *
     * @param info 图片信息
     * @param out 输出图片地址
     * @param logoPath logo图片地址
     * @throws WriterException
     * @throws IOException
     */
    public void MakeQrCodeWithLogo(final String info, final String out, final String logoPath)
            throws WriterException, IOException {
        final File outFile = new File(out);

        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }

        final BufferedImage image =
                this.toTopAndButtonImg(this.getBitMatrix(info), true, info, this.qrCodeConfig.getTitle());

        if (this.qrCodeConfig.getLogoPath() != null) {
            this.addLogo2QrCode(image, new File(this.qrCodeConfig.getLogoPath()));
        }

        ImageIO.write(image, QRCodeMaker.IMG_FORMATE, outFile);
    }

    /**
     * get bitMatrix from content
     *
     * @param conten qr_code info
     * @return
     * @throws WriterException
     */
    private BitMatrix getBitMatrix(final String conten) throws WriterException {
        final MultiFormatWriter writer = new MultiFormatWriter();

        final Map<EncodeHintType, Object> hint = new HashMap<>();
        hint.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hint.put(EncodeHintType.MARGIN, 1);
        return writer.encode(conten, BarcodeFormat.QR_CODE, this.PIC_WIDTH, this.PIC_HEIGHT, hint);
    }

    @SuppressWarnings("unused")
    private static BufferedImage toBufferedImg(final BitMatrix bitMatrix) {
        final int width = bitMatrix.getWidth();
        final int height = bitMatrix.getHeight();

        final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? QRCodeMaker.BLUE : QRCodeMaker.WHITE);
            }
        }

        return image;
    }

    private BufferedImage toTopAndButtonImg(final BitMatrix bitMatrix, final boolean isButtonDes, final String info,
            final String topMsg) {
        //info="编号："+info;

        final int width = bitMatrix.getWidth();
        final int height = bitMatrix.getHeight();
        final BufferedImage image =
                new BufferedImage(width, isButtonDes ? height + 60 : height, BufferedImage.TYPE_INT_RGB);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y + 30, bitMatrix.get(x, y) ? QRCodeMaker.BLACK : QRCodeMaker.WHITE);
            }
        }

        final Graphics2D graph = image.createGraphics();

        //标题
        final BufferedImage textImage2 =
                FontImage.getImage(topMsg, new Font("宋体", Font.BOLD, this.jssize(topMsg)), this.QR_SIZE, 30);
        final int width3 = textImage2.getWidth(null);
        final int height3 = textImage2.getHeight(null);
        final Image src2 = textImage2;
        graph.drawImage(src2, 0, 0, width3, height3, null);
        //结尾
        final BufferedImage textImage = FontImage.getImage(info, this.QR_SIZE, 30);
        final int width2 = textImage.getWidth(null);
        final int height2 = textImage.getHeight(null);
        final Image src = textImage;
        graph.drawImage(src, 0, this.QR_SIZE + 30, width2, height2, null);
        graph.dispose();
        return image;
    }

    private void addLogo2QrCode(final BufferedImage qrImage, final File logoFile) throws IOException {

        if (qrImage == null) {
            throw new RuntimeException("qrpic is null");
        }

        if (!logoFile.exists()) {
            throw new FileNotFoundException("can not found logo file at " + logoFile.getAbsolutePath());
        }

        final BufferedImage logo = ImageIO.read(logoFile);

        int logoWidth = logo.getWidth(null);
        int logoHeight = logo.getHeight(null);

        if ((qrImage.getWidth() / 5) < logoWidth) {
            logoWidth = qrImage.getWidth() / 5;
            logoHeight = (qrImage.getHeight() * logoWidth) / qrImage.getWidth();
        }

        // get logo position
        final int x = (qrImage.getWidth() - logoWidth) / 2;
        final int y = (qrImage.getHeight() - logoHeight) / 2;

        // draw logo on qr picture
        final Graphics2D graphics2D = qrImage.createGraphics();

        graphics2D.drawImage(logo, x, y, logoWidth, logoHeight, null);
        graphics2D.drawRoundRect(x, y, logoWidth, logoHeight, 6, 6);
        graphics2D.setStroke(new BasicStroke(QRCodeMaker.LOGO_BORDER_WIDTH));
        graphics2D.setColor(QRCodeMaker.LOGO_BORDER_COLOR);
        graphics2D.drawRect(x, y, logoWidth, logoHeight);

        graphics2D.dispose();
    }

    private int jssize(final String context) {
        final int length = context.length();
        return (this.QR_SIZE / length) - 1;
    }
}
